package com.shouxue.switchbutton;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import java.util.Locale;

import androidx.core.text.TextUtilsCompat;

public class SlideSwitch extends View {

    private static final String TAG = "SlideSwitch";

    /**
     * 按钮开关时的动画时长
     * 默认50ms
     */
    private final static int ANIM_TIME = 50;

    private int animTime;

    private Bitmap mBgOn;
    private Bitmap mBgOnDisabled;
    private Bitmap mBgOff;
    private Bitmap mBgOffDisabled;
    private Bitmap mThumbOn;
    private Bitmap mThumbOnDisabled;
    private Bitmap mThumbOff;
    private Bitmap mThumbOffDisabled;

    private Context mContext;
    private AttributeSet mAttrs;
    private Paint mPaint;
    private int mDefStyleAttr = -1;
    private Canvas mCanvas;

    private boolean mSelected = false;
    private boolean mEnabled = true;

    private float mLeft = 0;
    private int mTop;
    /**
     * 按钮开和关的间距
     */
    private float mDistance = 0;

    private boolean mInit = true;

    private ValueAnimator mAnimator;
    private boolean mIsRtl = false;

    public SlideSwitch(Context context) {
        this(context, null);
    }

    public SlideSwitch(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SlideSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        mAttrs = attrs;
        mDefStyleAttr = defStyleAttr;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SlideSwitch,
                defStyleAttr, 0);
        getAttr(typedArray);
        initPaint();
        mIsRtl = isRtl();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mIsRtl = isRtl();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
    }


    @Override
    public void setSelected(boolean selected) {
        super.setSelected(selected);
        if (selected != mSelected) {
            mSelected = selected;
            startAnimator(mSelected);
        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mCanvas = canvas;
        if (mBgOn == null || mBgOnDisabled == null || mThumbOn == null || mThumbOnDisabled == null
                || mBgOff == null || mBgOffDisabled == null || mThumbOff == null || mThumbOffDisabled == null) {
            return;
        }

        Log.i(TAG, "onDraw: mInit = " + mInit + ",mLeft = " + mLeft + ",mDistance = " + mDistance);

        if (mInit) {
            if (mAnimator != null && mAnimator.isRunning()) {
                mAnimator.end();
            }
            Bitmap trackBitmap = getCurTrackBitmap();
            if (trackBitmap != null) {
                canvas.drawBitmap(trackBitmap, 0, 0, mPaint);
            }

            Bitmap thumbBitmap = getCurThumbBitmap();
            if (thumbBitmap != null) {
                canvas.drawBitmap(thumbBitmap, getCurThumbDistance(), mTop, mPaint);
            }
            mInit = false;
        }
        else {
            if (!mIsRtl && mLeft < mDistance) {
                canvas.drawBitmap(isEnabledBg() ? mBgOff : mBgOffDisabled, 0, 0, mPaint);
                canvas.drawBitmap(isEnabledBg() ? mThumbOff : mThumbOffDisabled, mLeft, mTop, mPaint);
            }
            else {
                Bitmap trackBitmap = getCurTrackBitmap();
                if (trackBitmap != null) {
                    canvas.drawBitmap(trackBitmap, 0, 0, mPaint);
                }

                Bitmap thumbBitmap = getCurThumbBitmap();
                if (thumbBitmap != null) {
                    canvas.drawBitmap(thumbBitmap, mLeft, mTop, mPaint);
                }
            }
        }
    }

    private Bitmap getCurTrackBitmap() {
        if (isEnabledBg()) {
            return isSelected() ? mBgOn : mBgOff;
        }
        else {
            return isSelected() ? mBgOnDisabled : mBgOffDisabled;
        }
    }

    private Bitmap getCurThumbBitmap() {
        if (isEnabledBg()) {
            return isSelected() ? mThumbOn : mThumbOff;
        }
        else {
            return isSelected() ? mThumbOnDisabled : mThumbOffDisabled;
        }
    }

    private float getCurThumbDistance() {
        if (mIsRtl) {
            return isSelected() ? 0 : mDistance;
        }
        else {
            return isSelected() ? mDistance : 0;
        }
    }

    /**
     * 获取属性值
     *
     * @param typedArray
     */
    private void getAttr(TypedArray typedArray) {
        int bgOnId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_on_nor);
        mBgOn = BitmapFactory.decodeResource(getResources(), bgOnId);

        int bgOnDisabledId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_on_nor_d);
        mBgOnDisabled = BitmapFactory.decodeResource(getResources(), bgOnDisabledId);

        int bgOffId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_off_nor);
        mBgOff = BitmapFactory.decodeResource(getResources(), bgOffId);

        int bgOffDisabledId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_off_nor_d);
        mBgOffDisabled = BitmapFactory.decodeResource(getResources(), bgOffDisabledId);

        int thumbOnId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_opint);
        mThumbOn = BitmapFactory.decodeResource(getResources(), thumbOnId);

        int thumbOnDisabledId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_opint_d);
        mThumbOnDisabled = BitmapFactory.decodeResource(getResources(), thumbOnDisabledId);

        int thumbOffId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_opint);
        mThumbOff = BitmapFactory.decodeResource(getResources(), thumbOffId);

        int thumbOffDisabledId = typedArray.getResourceId(R.styleable.SlideSwitch_bgOn,
                R.mipmap.switch_opint_d);
        mThumbOffDisabled = BitmapFactory.decodeResource(getResources(), thumbOffDisabledId);

        animTime = typedArray.getInt(R.styleable.SlideSwitch_animTime, ANIM_TIME);

        if (mBgOn != null && mThumbOn != null) {
            mDistance = mBgOn.getWidth() - mThumbOn.getWidth();
            mTop = (mBgOn.getHeight() - mThumbOn.getHeight()) / 2;
        }

        typedArray.recycle();
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        invalidate();
    }

    public void setEnabledBg(boolean enabled) {
        this.mEnabled = enabled;
        invalidate();
    }

    private boolean isEnabledBg() {
        return isEnabled() && mEnabled;
    }

    private void initPaint() {
        mPaint = new Paint();
        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mPaint.setTypeface(Typeface.SANS_SERIF);
        mPaint.setColor(Color.WHITE);
    }

    private void startAnimator(boolean selected) {
        float start;
        float end;
        if (mIsRtl) {
            if (selected) {
                start = mDistance;
                end = 0;
            }
            else {
                start = 0;
                end = mDistance;
            }
        }
        else {
            if (selected) {
                start = 0;
                end = mDistance;
            }
            else {
                start = mDistance;
                end = 0;
            }
        }
        mAnimator = ValueAnimator.ofFloat(start, end);
        mAnimator.setDuration(animTime);
        mAnimator.setInterpolator(new LinearInterpolator());
        mAnimator.start();

        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                if (animation.getAnimatedValue() != null) {
                    mLeft = (Float) animation.getAnimatedValue();
                }
                postInvalidate();
            }
        });
    }

    private boolean isRtl() {
        boolean rtl =
                TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
        Log.i(TAG, "isRtl: rtl = " + rtl);
        return rtl;
    }

    public void refreshDrawableResource() {
        if (mContext == null || mAttrs == null || mDefStyleAttr == -1 || mCanvas == null) {
            return;
        }

        TypedArray typedArray = mContext.obtainStyledAttributes(mAttrs, R.styleable.SlideSwitch,
                mDefStyleAttr, 0);
        getAttr(typedArray);

        if (!mIsRtl && mLeft < mDistance) {
            mCanvas.drawBitmap(isEnabledBg() ? mBgOff : mBgOffDisabled, 0, 0, mPaint);
            mCanvas.drawBitmap(isEnabledBg() ? mThumbOff : mThumbOffDisabled, mLeft, mTop, mPaint);
        }
        else {
            Bitmap trackBitmap = getCurTrackBitmap();
            if (trackBitmap != null) {
                mCanvas.drawBitmap(trackBitmap, 0, 0, mPaint);
            }

            Bitmap thumbBitmap = getCurThumbBitmap();
            if (thumbBitmap != null) {
                mCanvas.drawBitmap(thumbBitmap, mLeft, mTop, mPaint);
            }
        }
    }
}
